package siruna.WE.core;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import siruna.WE.core.BlockFactory.FunctionalBlockFactory;
import siruna.WE.core.BlockFactory.VisualBlockFactory;
import siruna.WE.core.events.EventListFactory;
import siruna.WE.core.events.EventListener;
import siruna.WE.core.model.EventList;
import siruna.WE.core.model.FunctionalBlock;
import siruna.WE.core.model.VisualBlock;

public class XMLParser {
	Subject subject;
	int widgetId;
	private EventListener eh;
	private String deviceDependentFunctionBlocks;
	private String widgetName;

	public XMLParser(Subject subject, int id) {
		this.subject = subject;
		widgetId = id;
		eh = new EventListener();
		eh.setSubject(subject);

	}

	public Widget parseWidgetFile(ZipFile zipFile) {

		
		System.out.println("davd: "+zipFile.getName());
		ZipEntry entry = zipFile.getEntry("test.xml");

		System.out.println("new widget" + widgetId);
		Widget widget = new Widget(widgetId);
		widgetName = zipFile.getName().substring(0, zipFile.getName().lastIndexOf("."));
		try {
			InputStream is = zipFile.getInputStream(entry);

			try {
				Document doc = parseFile(is);

				widget.setVisblocks(verwerkWidgetFileVisual(doc, zipFile));
				widget.setEventlists(verwerkWidgetFileEvents(doc));
				widget
						.setFunctblocks(verwerkWidgetFileFunctional(doc,
								zipFile));

				eh.setWidget(widget);

				// implementaties van het Hardware specifieke deel ophalen

				HashMap<String, FunctionalBlock> hm = new HashMap<String, FunctionalBlock>();
				for (String s : widget.getFunctblocks().keySet()) {
					String name = widget.getFunctblocks().get(s).getClass()
							.getSimpleName();

					if (name.startsWith("Device")) {
						System.out.println("in de hasmap: " + s);
						hm.put(s, widget.getFunctblocks().get(s));
					}
				}

				HashMap<String, FunctionalBlock> ret = subject
						.getDevideFunctionalBlocks(hm);
				for (String s : ret.keySet()) {
					widget.getFunctblocks().put(s, ret.get(s));
				}

				widget.load();

			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return widget;
	}

	private LinkedHashMap<String, VisualBlock> verwerkWidgetFileVisual(
			Document doc, ZipFile zipFile) {
		NodeList vis = doc.getElementsByTagName("Page");

		VisualBlockFactory vbf = new VisualBlockFactory(eh, zipFile, widgetName);

		LinkedHashMap<String, VisualBlock> blocks = vbf.makeVisualBlocks(vis);

		// subject.updateWidget(widgetId);

		return blocks;
		// schrijf(vis);

		// System.out.println
		// schrijf(vis.item(0).getChildNodes());

	}

	private HashMap<String, FunctionalBlock> verwerkWidgetFileFunctional(
			Document doc, ZipFile zipFile) {
		NodeList vis = doc.getElementsByTagName("FunctionalBlocks");

		FunctionalBlockFactory fbf = new FunctionalBlockFactory(eh, zipFile,
				deviceDependentFunctionBlocks, widgetName);

		HashMap<String, FunctionalBlock> blocks = fbf.makeFunctionalBlocks(vis);

		// subject.updateWidget(widgetId);

		return blocks;
		// schrijf(vis);

		// System.out.println
		// schrijf(vis.item(0).getChildNodes());

	}

	private HashMap<String, EventList> verwerkWidgetFileEvents(Document doc) {
		NodeList vis = doc.getElementsByTagName("EventList");

		EventListFactory elf = new EventListFactory(eh,widgetName);

		HashMap<String, EventList> blocks = elf.makeEventLists(vis);

		for (String s : blocks.keySet()) {
			System.out.println("test: " + blocks.get(s).getId());

		}

		return blocks;

	}

	public Document parseFile(InputStream in) throws FactoryConfigurationError,
			ParserConfigurationException, SAXException, IOException {

		BufferedInputStream bis = new BufferedInputStream(in);

		// Create a factory
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		// Use the factory to create a builder
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document doc = builder.parse(bis);
		// Get a list of all elements in the document

		// NodeList list = doc.getElementsByTagName("*");

		// schrijf(list);

		return doc;
	}

	private void schrijf(NodeList list) {
		System.out.println("XML Elements: ");
		for (int i = 0; i < list.getLength(); i++) {
			// Get element
			if (list.item(i).getNodeType() == Document.ELEMENT_NODE) {

				Element element = (Element) list.item(i);
				System.out.println(element.getNodeName());

			}
		}
	}

	public void setDeviceFunctBlockLocation(String deviceDependentFunctionBlocks) {
		this.deviceDependentFunctionBlocks = deviceDependentFunctionBlocks;

	}

}
